package com.component.api.model.flow;

import cn.hutool.core.collection.CollUtil;
import com.alibaba.fastjson.JSON;
import com.component.api.AbstractComponent;
import com.component.api.excepiton.ComponentException;
import com.component.api.model.PortData;
import com.component.api.model.param.ParamPair;
import com.component.api.utils.ComponentUtils;
import com.google.common.graph.Graph;
import com.component.api.model.param.ComponentDefine;
import com.component.api.model.param.Port;
import lombok.Data;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 描述：
 * 排序节点
 *  用于前端解析排序
 * @author xianggj
 * @Date 2021/12/2 15:35
 **/
@Data
public class SortNodeInfo {

    public SortNodeInfo(NodeInfo nodeInfo, Graph<NodeInfo> graph) {
        this.nodeInfo = nodeInfo;
        Set<NodeInfo> predecessors = graph.predecessors(nodeInfo);
        if (!CollUtil.isEmpty(predecessors)){
            this.preNodes = predecessors.stream().map(e-> new SortNodeInfo(e, graph)).collect(Collectors.toSet());
        }

    }

    /**
     * 当前节点
     */
    private NodeInfo nodeInfo;

    /**
     * 前节点
     */
    private Set<SortNodeInfo> preNodes;

    /**
     * 后节点
     */
    private Set<SortNodeInfo> afterNodes;

    /**
     * 数字越小 越靠前
     * @return
     */
    public int getSort(){
        if (CollUtil.isEmpty(preNodes)){
            return 0;
        }
        Integer sort = preNodes.stream().collect(Collectors.summingInt(SortNodeInfo::getSort));
        return sort;
    }

    /**
     * 获取解析结果
     * @return
     */
    public List<PortData> getPortData(){
        String rule = nodeInfo.getRule();
        List<PortData> prePortData = new ArrayList<>();
        if (!CollUtil.isEmpty(preNodes)){
            prePortData = preNodes.stream().map(e->e.getPortData()).flatMap(e->e.stream()).collect(Collectors.toList());
        } else {
            //首节点 是否可以 首节点特点输入线为0
            ComponentDefine comdef = ComponentUtils.getComponentDefineByRule(rule);
            List<Port> ports = comdef.getPorts();
            //有输入 就不是首节点 放弃解析
            if (ports.stream().anyMatch(e->Port.IN.equals(e.getType()))){
                throw new ComponentException(String.format("源节点【%s】无输出字段", nodeInfo.getName()));
            }
        }
        List<PortData> portData = null;
        try {
            List<ParamPair> paramPairs = JSON.parseArray(nodeInfo.getParam(), ParamPair.class);
            AbstractComponent component = ComponentUtils.getComponentByRule(rule);
            portData = component.previewOutputColumns(prePortData, paramPairs);
            portData.stream().forEach(e->e.setNodeId(nodeInfo.getId()));
        } catch (Exception e) {
            e.printStackTrace();
            throw new ComponentException(String.format("节点【%s】字段解析出错：", nodeInfo.getName()), e);
        }
        return portData;
    }

}
